package service

import (
	"context"
	"fmt"
	"order_srv/basic/orderproto"
	"order_srv/handler/dao"
	"order_srv/handler/models"
	"time"
)

// GetLogsByUser 根据用户ID获取操作日志
func (s *Server) GetLogsByUser(ctx context.Context, req *__.GetLogsByUserReq) (*__.GetLogsByUserResp, error) {
	// 验证请求参数
	if req.UserId == "" {
		return &__.GetLogsByUserResp{
			Code:    400,
			Message: "用户ID不能为空",
		}, nil
	}

	// 设置默认值
	page := req.Page
	if page <= 0 {
		page = 1
	}
	pageSize := req.PageSize
	if pageSize <= 0 {
		pageSize = 20
	}
	if pageSize > 100 {
		pageSize = 100
	}

	// 获取日志
	logs, total, err := dao.GetLogsByUser(ctx, req.UserId, page, pageSize)
	if err != nil {
		return &__.GetLogsByUserResp{
			Code:    500,
			Message: fmt.Sprintf("获取用户日志失败: %v", err),
		}, nil
	}

	// 转换为proto格式
	var protoLogs []*__.OperationLogInfo
	for _, log := range logs {
		protoLog := s.convertLogToProto(log)
		protoLogs = append(protoLogs, protoLog)
	}

	return &__.GetLogsByUserResp{
		Code:     200,
		Message:  "获取用户日志成功",
		Logs:     protoLogs,
		Total:    total,
		Page:     page,
		PageSize: pageSize,
	}, nil
}

// GetLogsByModule 根据模块获取操作日志
func (s *Server) GetLogsByModule(ctx context.Context, req *__.GetLogsByModuleReq) (*__.GetLogsByModuleResp, error) {
	// 验证请求参数
	if req.Module == "" {
		return &__.GetLogsByModuleResp{
			Code:    400,
			Message: "模块名称不能为空",
		}, nil
	}

	// 设置默认值
	page := req.Page
	if page <= 0 {
		page = 1
	}
	pageSize := req.PageSize
	if pageSize <= 0 {
		pageSize = 20
	}
	if pageSize > 100 {
		pageSize = 100
	}

	// 获取日志
	logs, total, err := dao.GetLogsByModule(ctx, req.Module, page, pageSize)
	if err != nil {
		return &__.GetLogsByModuleResp{
			Code:    500,
			Message: fmt.Sprintf("获取模块日志失败: %v", err),
		}, nil
	}

	// 转换为proto格式
	var protoLogs []*__.OperationLogInfo
	for _, log := range logs {
		protoLog := s.convertLogToProto(log)
		protoLogs = append(protoLogs, protoLog)
	}

	return &__.GetLogsByModuleResp{
		Code:     200,
		Message:  "获取模块日志成功",
		Logs:     protoLogs,
		Total:    total,
		Page:     page,
		PageSize: pageSize,
	}, nil
}

// GetLogsByResource 根据资源获取操作日志
func (s *Server) GetLogsByResource(ctx context.Context, req *__.GetLogsByResourceReq) (*__.GetLogsByResourceResp, error) {
	// 验证请求参数
	if req.ResourceType == "" || req.ResourceId == "" {
		return &__.GetLogsByResourceResp{
			Code:    400,
			Message: "资源类型和资源ID不能为空",
		}, nil
	}

	// 设置默认值
	page := req.Page
	if page <= 0 {
		page = 1
	}
	pageSize := req.PageSize
	if pageSize <= 0 {
		pageSize = 20
	}
	if pageSize > 100 {
		pageSize = 100
	}

	// 获取日志
	logs, total, err := dao.GetLogsByResource(ctx, req.ResourceType, req.ResourceId, page, pageSize)
	if err != nil {
		return &__.GetLogsByResourceResp{
			Code:    500,
			Message: fmt.Sprintf("获取资源日志失败: %v", err),
		}, nil
	}

	// 转换为proto格式
	var protoLogs []*__.OperationLogInfo
	for _, log := range logs {
		protoLog := s.convertLogToProto(log)
		protoLogs = append(protoLogs, protoLog)
	}

	return &__.GetLogsByResourceResp{
		Code:     200,
		Message:  "获取资源日志成功",
		Logs:     protoLogs,
		Total:    total,
		Page:     page,
		PageSize: pageSize,
	}, nil
}

// GetLogsByCondition 根据条件获取操作日志
func (s *Server) GetLogsByCondition(ctx context.Context, req *__.GetLogsByConditionReq) (*__.GetLogsByConditionResp, error) {
	// 设置默认值
	page := req.Page
	if page <= 0 {
		page = 1
	}
	pageSize := req.PageSize
	if pageSize <= 0 {
		pageSize = 20
	}
	if pageSize > 100 {
		pageSize = 100
	}

	// 构建查询条件
	condition := &dao.LogQueryCondition{
		UserID:       req.UserId,
		Module:       req.Module,
		Operation:    req.Operation,
		ResourceType: req.ResourceType,
		ResourceID:   req.ResourceId,
		LogType:      req.LogType,
		Result:       req.Result,
		IPAddress:    req.IpAddress,
		Page:         page,
		PageSize:     pageSize,
	}

	// 解析时间
	if req.StartTime != "" {
		if startTime, err := time.Parse(time.RFC3339, req.StartTime); err == nil {
			condition.StartTime = &startTime
		}
	}
	if req.EndTime != "" {
		if endTime, err := time.Parse(time.RFC3339, req.EndTime); err == nil {
			condition.EndTime = &endTime
		}
	}

	// 获取日志
	logs, total, err := dao.GetLogsByCondition(ctx, condition)
	if err != nil {
		return &__.GetLogsByConditionResp{
			Code:    500,
			Message: fmt.Sprintf("获取条件日志失败: %v", err),
		}, nil
	}

	// 转换为proto格式
	var protoLogs []*__.OperationLogInfo
	for _, log := range logs {
		protoLog := s.convertLogToProto(log)
		protoLogs = append(protoLogs, protoLog)
	}

	return &__.GetLogsByConditionResp{
		Code:     200,
		Message:  "获取条件日志成功",
		Logs:     protoLogs,
		Total:    total,
		Page:     page,
		PageSize: pageSize,
	}, nil
}

// GetLogStatistics 获取日志统计信息
func (s *Server) GetLogStatistics(ctx context.Context, req *__.GetLogStatisticsReq) (*__.GetLogStatisticsResp, error) {
	// 设置默认时间范围
	startTime := time.Now().AddDate(0, 0, -30) // 默认30天前
	endTime := time.Now()

	// 解析时间
	if req.StartTime != "" {
		if parsedTime, err := time.Parse(time.RFC3339, req.StartTime); err == nil {
			startTime = parsedTime
		}
	}
	if req.EndTime != "" {
		if parsedTime, err := time.Parse(time.RFC3339, req.EndTime); err == nil {
			endTime = parsedTime
		}
	}

	// 获取统计信息
	stats, err := dao.GetLogStatistics(ctx, startTime, endTime)
	if err != nil {
		return &__.GetLogStatisticsResp{
			Code:    500,
			Message: fmt.Sprintf("获取日志统计失败: %v", err),
		}, nil
	}

	return &__.GetLogStatisticsResp{
		Code:    200,
		Message: "获取日志统计成功",
		Stats:   fmt.Sprintf("%+v", stats),
	}, nil
}

// DeleteOldLogs 删除旧日志
func (s *Server) DeleteOldLogs(ctx context.Context, req *__.DeleteOldLogsReq) (*__.DeleteOldLogsResp, error) {
	// 验证请求参数
	if req.BeforeTime == "" {
		return &__.DeleteOldLogsResp{
			Code:    400,
			Message: "删除时间不能为空",
		}, nil
	}

	// 解析时间
	beforeTime, err := time.Parse(time.RFC3339, req.BeforeTime)
	if err != nil {
		return &__.DeleteOldLogsResp{
			Code:    400,
			Message: "时间格式错误",
		}, nil
	}

	// 删除旧日志
	err = dao.DeleteOldLogs(ctx, beforeTime)
	if err != nil {
		return &__.DeleteOldLogsResp{
			Code:    500,
			Message: fmt.Sprintf("删除旧日志失败: %v", err),
		}, nil
	}

	return &__.DeleteOldLogsResp{
		Code:    200,
		Message: "删除旧日志成功",
	}, nil
}

// convertLogToProto 将日志模型转换为proto格式
func (s *Server) convertLogToProto(log models.OperationLog) *__.OperationLogInfo {
	return &__.OperationLogInfo{
		Id:            log.ID,
		LogType:       log.LogType,
		Module:        log.Module,
		Operation:     log.Operation,
		ResourceType:  log.ResourceType,
		ResourceId:    log.ResourceID,
		ResourceName:  log.ResourceName,
		UserId:        log.UserID,
		UserName:      log.UserName,
		UserType:      log.UserType,
		IpAddress:     log.IPAddress,
		UserAgent:     log.UserAgent,
		RequestMethod: log.RequestMethod,
		RequestUrl:    log.RequestURL,
		RequestParams: log.RequestParams,
		ResponseCode:  log.ResponseCode,
		ResponseTime:  log.ResponseTime,
		OldData:       log.OldData,
		NewData:       log.NewData,
		ChangeFields:  log.ChangeFields,
		Result:        log.Result,
		ErrorMessage:  log.ErrorMessage,
		Description:   log.Description,
		ExtraData:     log.ExtraData,
		CreatedAt:     log.CreatedAt.Format(time.RFC3339),
		UpdatedAt:     log.UpdatedAt.Format(time.RFC3339),
	}
}

// LogOperation 记录操作的便捷方法
func (s *Server) LogOperation(ctx context.Context, logType, module, operation, resourceType, resourceID, userID, userName, userType, description string) error {
	log := &models.OperationLog{
		LogType:      logType,
		Module:       module,
		Operation:    operation,
		ResourceType: resourceType,
		ResourceID:   resourceID,
		UserID:       userID,
		UserName:     userName,
		UserType:     userType,
		Result:       models.ResultSuccess,
		Description:  description,
		CreatedAt:    time.Now(),
	}

	return dao.CreateLog(ctx, log)
}

// LogError 记录错误的便捷方法
func (s *Server) LogError(ctx context.Context, module, operation, resourceType, resourceID, userID, userName, userType, errorMessage, description string) error {
	log := &models.OperationLog{
		LogType:      models.LogTypeError,
		Module:       module,
		Operation:    operation,
		ResourceType: resourceType,
		ResourceID:   resourceID,
		UserID:       userID,
		UserName:     userName,
		UserType:     userType,
		Result:       models.ResultError,
		ErrorMessage: errorMessage,
		Description:  description,
		CreatedAt:    time.Now(),
	}

	return dao.CreateLog(ctx, log)
}
